package cc.vv.party.service.impl;

import cc.vv.party.beans.model.*
import cc.vv.party.beans.model.Unit
import cc.vv.party.beans.vo.*
import cc.vv.party.common.base.BaseServiceImpl
import cc.vv.party.common.constants.StatusCode
import cc.vv.party.common.constants.SysConsts
import cc.vv.party.common.constants.enums.OrgType
import cc.vv.party.common.constants.enums.RoleType
import cc.vv.party.common.ext.toTree
import cc.vv.party.common.ext.uuid
import cc.vv.party.exception.BizException
import cc.vv.party.mapper.OrgMapper
import cc.vv.party.param.OrgEditParam
import cc.vv.party.param.OrgParam
import cc.vv.party.service.*
import com.baomidou.mybatisplus.mapper.EntityWrapper
import com.baomidou.mybatisplus.plugins.Page
import commonx.core.content.transfer
import commonx.core.content.transferEntries
import org.apache.commons.collections.CollectionUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

/**
 * <p>
 * 组织机构 服务实现类
 * </p>
 *
 * @author Gyb
 * @since 2018-10-12
 */
@Service
open class OrgServiceImpl : BaseServiceImpl<OrgMapper, Org>(), OrgService {

    @Autowired
    lateinit var orgAdminService: OrgAdminService

    @Autowired
    lateinit var userRoleService: UserRoleService

    @Autowired
    lateinit var roleService: RoleService

    @Autowired
    lateinit var societyOrgService: SocietyOrgService

    @Autowired
    lateinit var societyOrgDynamicService: SocietyOrgDynamicService

    @Autowired
    lateinit var communityPartyCommitteeService: CommunityPartyCommitteeService

    @Autowired
    lateinit var unitService: UnitService

    @Autowired
    lateinit var pmcAccountorService: PmcAccountorService

    @Autowired
    lateinit var pmcPersonService: PmcPersonService

    @Autowired
    lateinit var userService: UserService

    @Transactional
    override fun addOrg(param: OrgParam, currentUserId: String, currentAccount: String): OrgVO {
        if (param.adminList == null || param.adminList!!.isEmpty()) {
            throw BizException(StatusCode.MISSING_REQUIRE_FIELD.statusCode, "组织机构管理员至少需要存在一个")
        }
        val parent = this.baseMapper.selectById(param.parentId) ?: throw BizException(
            StatusCode.FIELD_VALUE_ERROR.statusCode,
            "parentId不存在"
        )
        val org = Org()
        org.id = uuid()
        org.introduction = param.introduction
        org.mobile = param.mobile
        org.location = param.location
        org.name = param.name
        org.type = param.type
        org.path = "${parent.path}-${org.id}"
        org.parentId = param.parentId
        org.createUser = currentUserId
        insert(org)

        //判断管理员是否已经存在
        val accountList = param.adminList!!.distinctBy { it.account }.map { it.account!! }

        pmcAccountorService.checkAccountListExists(accountList = accountList)

        val map = orgAdminService.selectList(
            EntityWrapper<OrgAdmin>().`in`(
                "user_account",
                accountList.joinToString(separator = ",")
            )
        ).groupBy { it.userAccount }
        if (map.isNotEmpty()) {
            map.any {
                val any = it.value.isNotEmpty()
                if (any) {
                    throw BizException(StatusCode.ERROR.statusCode, "管理员${it.key}已经存在")
                }
                any
            }
        }
        val roleMap = roleService.selectList(EntityWrapper<Role>()).associateBy { it.type }
        val orgAdminList = mutableListOf<OrgAdmin>()
        val userRoleList = mutableListOf<UserRole>()
        for (admin in param.adminList!!) {
            val orgAdmin = OrgAdmin()
            orgAdmin.orgId = org.id
            orgAdmin.userName = admin.name
            orgAdmin.userAccount = admin.account
            orgAdmin.createUser = currentUserId
            orgAdminList.add(orgAdmin)

            val userRole = UserRole()
            userRole.userAccount = orgAdmin.userAccount
            userRole.roleId = roleMap[RoleType.enumOf(admin.roleType!!)]!!.id.toString()
            userRole.createUser = currentUserId
            userRoleList.add(userRole)
        }
        userRoleService.insertBatch(userRoleList)
        orgAdminService.insertBatch(orgAdminList)
        return getManagedOrgList(currentAccount)
    }

    override fun getOrgList(): OrgVO {
        val list =
            baseMapper.selectList(EntityWrapper<Org>().orderBy("p_id, create_time", true)).transferEntries<OrgVO>()
        list.forEach { it.introduction = null }
        return (list as List<OrgVO>).toTree()
    }

    override fun getManagedOrgList(currentAccount: String): OrgVO {
        if (currentAccount == "admin") {
            return getOrgList()
        }
        return findUserOrgAndChildren(currentAccount).toTree()
    }

    override fun getOrgDetailById(orgId: String): OrgVO {
        val org = selectById(orgId) ?: throw BizException(StatusCode.FIELD_VALUE_ERROR.statusCode, "组织机构不存在")
        val orgVo = org.transfer<OrgVO>()
        val orgAdminList =
            orgAdminService.selectList(EntityWrapper<OrgAdmin>().eq("org_id", orgId)).transferEntries<OrgAdminVO>()
        val userAccounts = orgAdminList.map { it.userAccount!! }.toList()
        if (CollectionUtils.isNotEmpty(userAccounts)) {
            val partyMemberList =
                pmcPersonService.selectPartyMemberByAccounts(userAccounts).associateBy { it.userAccount }
            orgAdminList.forEach {
                val member = partyMemberList[it.userAccount]
                it.userPhoto = member?.faceUrl
                it.userMobile = member?.mobile
                it.roleType = when (org.type) {
                    OrgType.AREA -> RoleType.AREA_ADMIN.roleName
                    OrgType.STREET -> RoleType.STREET_ADMIN.roleName
                    OrgType.SECTION -> RoleType.SECTION_ADMIN.roleName
                    OrgType.GRID -> RoleType.GRID_ADMIN.roleName
                    OrgType.UNIT -> RoleType.UNIT_ADMIN.roleName
                    OrgType.ORG -> RoleType.ORG_ADMIN.roleName
                    OrgType.BUILDING_TEAM -> RoleType.BUILDING_TEAM_ADMIN.roleName
                    OrgType.PARTY_MEMBER -> RoleType.PARTY_MEMBER.roleName
                    OrgType.CENTER -> RoleType.CENTER_ADMIN.roleName
                    OrgType.BRANCH -> RoleType.BRANCH_ADMIN.roleName
                    OrgType.JDLXHY -> RoleType.JDLXHY_ADMIN.roleName
                    OrgType.TEAM -> RoleType.TEAM_ADMIN.roleName
                    OrgType.FGDJ -> RoleType.FGDJ_ADMIN.roleName
                    OrgType.COMMITTEE -> RoleType.SECTION_COMMITTEE_ADMIN.roleName
                    else -> null
                }
            }
            orgVo.adminList = orgAdminList as MutableList<OrgAdminVO>
        }
        return orgVo
    }

    @Transactional
    override fun updateOrg(param: OrgEditParam, currentUserId: String, currentAccount: String): OrgVO {
        if (param.adminList == null || param.adminList!!.isEmpty()) {
            throw BizException(StatusCode.MISSING_REQUIRE_FIELD.statusCode, "组织机构管理员至少需要存在一个")
        }
        if (param.id.isNullOrEmpty()) {
            throw BizException(StatusCode.FIELD_VALUE_ERROR.statusCode, "缺少参数组织机构id")
        }
        //查询之前的组织信息，判断是否存在
        val org = selectById(param.id) ?: throw BizException(StatusCode.FIELD_VALUE_ERROR.statusCode, "组织机构不存在")
        //查询组织机构管理员列表
        val orgAdminIdList =
            orgAdminService.selectList(EntityWrapper<OrgAdmin>().eq("org_id", org.id)).map { it.userAccount }

        //循环判断新的管理员和之前的是否有变更
        var isAdminChanged = false
        if (param.adminList != null && param.adminList!!.isNotEmpty()) {
            for (admin in param.adminList!!) {
                if (admin.account.isNullOrEmpty()) {
                    throw BizException(StatusCode.MISSING_REQUIRE_FIELD.statusCode, "缺少参数\"管理员账号\"")
                }
                if (!orgAdminIdList.contains(admin.account)) {
                    isAdminChanged = true
                    break
                }
            }
        }

        org.introduction = param.introduction
        org.mobile = param.mobile
        org.name = param.name
        org.location = param.location
        updateById(org)

        //如果管理员变更过，则删掉所有的管理员关联信息，重新生成关联，并且判断是否存在重复
        if (isAdminChanged) {
            //删除之前的组织机构和管理员的关联
            orgAdminService.delete(EntityWrapper<OrgAdmin>().eq("org_id", org.id))

            //判断管理员是否已经存在
            val accountList = param.adminList!!.distinctBy { it.account }.map { it.account }
            val map = orgAdminService.selectList(
                EntityWrapper<OrgAdmin>().`in`(
                    "user_account",
                    accountList.joinToString(separator = ",")
                )
            ).groupBy { it.userAccount }
            if (map.isNotEmpty()) {
                map.any {
                    val any = it.value.isNotEmpty()
                    if (any) {
                        throw BizException(StatusCode.ERROR.statusCode, "管理员${it.key}已经存在")
                    }
                    any
                }
            }

            val roleMap = roleService.selectList(EntityWrapper<Role>()).associateBy { it.type }
            val orgAdminList = mutableListOf<OrgAdmin>()
            val userRoleList = mutableListOf<UserRole>()
            for (admin in param.adminList!!) {
                //删除之前的关联关系
                val roleId = roleMap[RoleType.enumOf(admin.roleType!!)]!!.id.toString()
                userRoleService.delete(
                    EntityWrapper<UserRole>().eq("user_account", admin.account).eq(
                        "role_id",
                        roleId
                    )
                )

                val orgAdmin = OrgAdmin()
                orgAdmin.orgId = org.id
                orgAdmin.userName = admin.name
                orgAdmin.userAccount = admin.account
                orgAdmin.createUser = currentUserId
                orgAdminList.add(orgAdmin)

                val userRole = UserRole()
                userRole.userAccount = orgAdmin.userAccount
                userRole.roleId = roleId
                userRole.createUser = currentUserId
                userRoleList.add(userRole)
            }
            userRoleService.insertBatch(userRoleList)
            orgAdminService.insertBatch(orgAdminList)
        } else {
            //如果账号没发生过变化，则更新其他字段
            val map = orgAdminService.selectList(
                EntityWrapper<OrgAdmin>().`in`(
                    "user_account",
                    param.adminList!!.map { it.account }.joinToString(separator = ",")
                )
            ).associateBy { it.userAccount }
            val orgAdminList = mutableListOf<OrgAdmin>()
            for (admin in param.adminList!!) {
                val orgAdmin = map[admin.account]
                orgAdmin!!.orgId = org.id
                orgAdmin.userName = admin.name
                orgAdminList.add(orgAdmin)
            }
            orgAdminService.updateBatchById(orgAdminList)
        }
        return getManagedOrgList(currentAccount)
    }


    @Transactional
    override fun deleteOrg(orgId: String, currentAccount: String): OrgVO {
        val deleteOrg = selectById(orgId) ?: throw BizException(StatusCode.FIELD_VALUE_ERROR.statusCode, "组织机构不存在")
        if (deleteOrg.type == OrgType.STREET || deleteOrg.type == OrgType.SECTION || deleteOrg.type == OrgType.GRID || deleteOrg.type == OrgType.UNIT) {
            val entityWrapper = EntityWrapper<User>()
            when (deleteOrg.type) {
                OrgType.STREET -> {
                    entityWrapper.eq("street", deleteOrg.id)
                }
                OrgType.SECTION -> {
                    entityWrapper.eq("community", deleteOrg.id)
                }
                OrgType.GRID -> {
                    entityWrapper.eq("grid", deleteOrg.id)
                }
                OrgType.UNIT -> {
                    entityWrapper.eq("workCompany", deleteOrg.id)
                }
            }
            if (userService.selectCount(entityWrapper) > 0) {
                throw BizException(StatusCode.ORG_HAS_MEMBER)
            }
        }
        val idList = baseMapper.selectList(EntityWrapper<Org>().like("path", deleteOrg.id)).map { it.id }.toList()
        deleteBatchIds(idList)
        val orgAdminAccountList =
            orgAdminService.selectList(EntityWrapper<OrgAdmin>().`in`("org_id", idList)).map { it.userAccount }
        orgAdminService.delete(EntityWrapper<OrgAdmin>().`in`("org_id", idList))
        var roleIdList: List<String>? = null
        when (deleteOrg.type) {
            OrgType.STREET -> {
                roleIdList = roleService.selectList(
                    EntityWrapper<Role>().`in`(
                        "type", arrayListOf(
                            RoleType.STREET_ADMIN, RoleType.SECTION_ADMIN, RoleType.GRID_ADMIN,
                            RoleType.UNIT_ADMIN, RoleType.CENTER_ADMIN, RoleType.BUILDING_TEAM_ADMIN
                        )
                    )
                ).map { it.id!! }
            }
            OrgType.SECTION -> {
                roleIdList = roleService.selectList(
                    EntityWrapper<Role>().`in`(
                        "type", arrayListOf(
                            RoleType.SECTION_ADMIN, RoleType.GRID_ADMIN,
                            RoleType.UNIT_ADMIN, RoleType.CENTER_ADMIN, RoleType.BUILDING_TEAM_ADMIN
                        )
                    )
                ).map { it.id!! }
            }
            OrgType.GRID -> {
                roleIdList = roleService.selectList(
                    EntityWrapper<Role>().`in`(
                        "type", arrayListOf(
                            RoleType.GRID_ADMIN, RoleType.CENTER_ADMIN, RoleType.BUILDING_TEAM_ADMIN
                        )
                    )
                ).map { it.id!! }
            }
            OrgType.UNIT -> {
                roleIdList = roleService.selectList(
                    EntityWrapper<Role>().eq("type", RoleType.UNIT_ADMIN)
                ).map { it.id!! }
            }
        }
        if (roleIdList != null && roleIdList.isNotEmpty()) {
            userRoleService.delete(
                EntityWrapper<UserRole>().`in`("user_account", orgAdminAccountList).`in`(
                    "role_id",
                    roleIdList
                )
            )
        }
        return getManagedOrgList(currentAccount)
    }

    override fun findOrgByUserAccount(account: String): List<OrgVO> {
        return this.baseMapper.findOrgListByAccount(account)
    }

    override fun getCommunityAndChildrenById(communityId: String): CommunityVO {
        val unitList =
            unitService.selectList(EntityWrapper<Unit>().eq("community", communityId)).transferEntries<UnitVO>()
        val societyOrgList =
            societyOrgService.selectPage(Page(1, 10), EntityWrapper<SocietyOrg>().eq("community", communityId))
                .records.transferEntries<SocietyOrgVO>()
        val dynamicList = societyOrgDynamicService.selectPage(
            Page(1, 10),
            EntityWrapper<SocietyOrgDynamic>().eq("community_id", communityId)
        ).records.transferEntries<SocietyOrgDynamicVO>()

        val committee = (communityPartyCommitteeService.selectOne(
            EntityWrapper<CommunityPartyCommittee>().eq(
                "community",
                communityId
            )
        ) ?: throw BizException(StatusCode.MESSAGE_NOT_EXIST)).transfer<CommunityPartyCommitteeVO>()
        val community = CommunityVO()
        community.committeeIntro = committee.partyCommitteeyIntroduction
        community.gridList = getGridListByCommunityId(communityId)
        community.societyOrgDynamicList = dynamicList as MutableList<SocietyOrgDynamicVO>
        community.societyOrgList = societyOrgList as MutableList<SocietyOrgVO>
        community.unitList = unitList as MutableList<UnitVO>
        community.communityId = communityId
        community.title = committee.partyCommitteeName
        community.name = committee.principalName
        community.mobile = committee.principalAccount
        return community
    }

    override fun getGridListByCommunityId(communityId: String): MutableList<OrgVO> {
        return this.selectList(EntityWrapper<Org>().eq("p_id", communityId)).transferEntries<OrgVO>() as MutableList
    }

    override fun getOrgListByIds(orgIds: List<String>): List<OrgVO> {
        return selectBatchIds(orgIds).transferEntries<OrgVO>() as List<OrgVO>
    }

    /**
     * 获取当前用户所管理的组织结构列表及子集合列表
     */
    override fun findUserOrgAndChildren(account: String): List<OrgVO> {
        return this.baseMapper.findUserOrgAndChildren(account)
    }

    override fun findPartyNode(type: String?, nodeId: String?): List<NodeVO> {
        if (type.isNullOrEmpty()) {
            return this.baseMapper.findRegionList(nodeId)
        }
        if (nodeId.isNullOrEmpty()) {
            throw BizException(StatusCode.MISSING_REQUIRE_FIELD.statusCode, "缺少参数NodeId")
        }
        val result = mutableListOf<NodeVO>()
        when (type) {
            SysConsts.BranchType.REGION_LEVEL_DISTRICT -> {
                val regionNodeList = this.baseMapper.findRegionList(nodeId)
                val partyWorkCommitteeNodeList = this.baseMapper.findPartyWorkCommitteeList()
                val partyCommitteeNodeList = this.baseMapper.findPartyCommitteeList(type, nodeId!!)
                result.addAll(regionNodeList)
                result.addAll(partyWorkCommitteeNodeList)
                result.addAll(partyCommitteeNodeList)
                return result
            }
            SysConsts.BranchType.PARTY_WORK_COMMITTEE, SysConsts.BranchType.PARTY_COMMITTEE -> {
                val partyCommitteeNodeList = this.baseMapper.findPartyCommitteeList(type, nodeId!!)
                val partyTotalBranchNodeList = this.baseMapper.findPartyTotalBranchList(type, nodeId)
                val partyBranchNodeList = this.baseMapper.findPartyBranchList(type, nodeId)
                result.addAll(partyCommitteeNodeList)
                result.addAll(partyTotalBranchNodeList)
                result.addAll(partyBranchNodeList)
                return result
            }
            SysConsts.BranchType.PARTY_TOTAL_BRANCH, SysConsts.BranchType.PARTY_BRANCH -> {
                result.addAll(this.baseMapper.findPartyBranchList(type, nodeId!!))
            }
        }
        return result
    }

    override fun findAppSatistics(year: Int, street: String?, community: String?, grid: String?): Map<Int, Int> {
        var list = baseMapper.findAppSatistics(year, street, community, grid)
        var map = HashMap<Int, Int>()
        if (CollectionUtils.isNotEmpty(list)) {
            for (temp in list) {
                map[temp["type"]!!.toInt()] = temp["num"]!!.toInt()
            }
        }
        return map;
    }
}
